home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 20 / Cream of the Crop 20 (Terry Blount) (1996).iso / math / alged34.zip / ALGEDSRC.ZIP / ALGFILE.C < prev    next >
C/C++ Source or Header  |  1996-06-06  |  14KB  |  525 lines

  1. /*--------------------------------------------------------------------
  2.    Alged:  Algebra Editor    henckel@vnet.ibm.com
  3.  
  4.    Copyright (c) 1994 John Henckel
  5.    Permission to use, copy, modify, distribute and sell this software
  6.    and its documentation for any purpose is hereby granted without fee,
  7.    provided that the above copyright notice appear in all copies.
  8. */
  9. #include "alged.h"
  10. /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  11.  
  12.     The following functions relate to reading and writing data files.
  13. */
  14. #define push(tt) do { tt->next = tos; tos = tt; } while(0)
  15. #define pop(tt) do { tt=tos; \
  16.    if (!tos) printf(msg[1]); else tos=tos->next; } while(0)
  17. #define pushr(tt) do { tt->next = r; r = tt; } while(0)
  18. #define popr(tt) do { tt=r; \
  19.    if (!r) printf(msg[2]); else r=r->next; } while(0)
  20.  
  21.            /*   = f + - * / ^ V N ? ( ) ,   used by infix read/write */
  22. int wpr[10] = { 0,8,2,2,4,4,6,8,8,8 };
  23. int rpr[15] = { 0,1,2,2,4,4,6,8,8,8,1,2,2 };
  24.  
  25. /* start-paren and end-paren, these are used as pseudo tokens. */
  26. #define SPA 10
  27. #define EPA 11
  28. #define CMA 12
  29. #define coper "=()+-*/^,"
  30. #define numer "0123456789."
  31. static char txt[2000];
  32. char gdriver[80] = "";        // these three lines are exported to algraph.c
  33. int gmode,pst,psz;
  34. double lightx=1,lighty=3,lightz=2;  // light source location
  35. static int stoe=0;        // see note in writetree
  36.  
  37. /*-----------------------------------------------------------------
  38.    parse option
  39. */
  40. void parse_option(FILE *f, char *b) {
  41.   int i=0; double t;
  42.   switch (*b) {
  43.     case 's': fscanf(f,"%d",&bold1); break;
  44.     case 'i': fscanf(f,"%d",&bold2); break;
  45.     case 'c': fscanf(f,"%d",&norm); break;
  46.     case 'm': fscanf(f,"%d",&mcolor); break;
  47.     case 'e': fscanf(f,"%d",&sigdig); break;
  48.     case 'd': fscanf(f,"%lg",&maxrat); break;
  49.     case 'p': fscanf(f,"%d",&maxpow); break;
  50.     case 'a': fscanf(f,"%d",&ch8); break;
  51.     case 'v': fscanf(f,"%d",&i); directvideo=(i>0); break;
  52.     case 'y': fscanf(f,"%d",&yadj); break;
  53.     case '.': fscanf(f,"%d",&point); break;
  54.     case 'l': fscanf(f,"%3s",lang); break;
  55.     case 'f': fscanf(f,"%d",&postfix); break;
  56.     case 'g': fscanf(f,"%s %d %d %d",gdriver,&gmode,&pst,&psz); break;
  57.     case 'r': fscanf(f,"%lg %lg %lg",&lightx,&lighty,&lightz);
  58.               t = hypot(lightx,hypot(lighty,lightz));
  59.               if (t < 1E-20) lighty=1;
  60.               else { lightx/=t; lighty/=t; lightz/=t; }
  61.               break;
  62.   }
  63. }
  64. /*-----------------------------------------------------------------
  65.    get one token from the file
  66.    if nn=1 then negative signs are treated as operators.
  67. */
  68. node *gettoken(FILE *f,int nn) {
  69.   int c,i;
  70.   static char buf[80];
  71.   double t;
  72.   node *p;
  73.   do {
  74.     c = fgetc(f);
  75.     if (c==';') do { c=fgetc(f); } while (c>0 && c!=10);
  76.     if (c=='?') {
  77.       fscanf(f,"%s",buf);
  78.       parse_option(f,buf);
  79.       c=0;
  80.     }
  81.     else if (c=='"') {
  82.       i = strlen(txt);
  83. /*      txt[i]=c;
  84.       fgets(txt+i+1,sizeof txt-i-2,f); */
  85.       fgets(txt+i,sizeof txt-i-1,f);
  86.       strcat(txt,"\r"); c=0;
  87.     }
  88.     else if (c=='@') {
  89.       fscanf(f,"%s",buf);
  90.       p = newvar(buf);
  91.       p->kind = FUN;
  92.       return p;
  93.     }
  94.     else if (c<0) return NULL;    /* EOF */
  95.   } while (c<=' ');
  96.   if (c=='*') return newoper(MUL);
  97.   if (c=='/') return newoper(DIV);
  98.   if (c=='^') return newoper(EXP);
  99.   if (c==')') return newoper(EPA);
  100.   if (c=='(') return newoper(SPA);
  101.   if (c=='=') return newoper(EQU);
  102.   if (c=='+') return newoper(ADD);
  103.   if (c==',') return newoper(CMA);
  104.   if (c=='-') {
  105.     if (nn) return newoper(SUB);
  106.     c = fgetc(f);               /* look ahead */
  107.     ungetc(c,f);
  108.     if (strchr(numer,c)) { t=0;
  109.       fscanf(f,"%lg",&t);
  110.       return newnum(-t);
  111.     }
  112.     else {
  113.       printf(msg[34]); pause;     // unary minus warning
  114.       return newnum(-1);
  115.     }
  116.   }
  117.   if (strchr(numer,c)) {
  118.     ungetc(c,f);
  119.     fscanf(f,"%lg",&t);
  120.     return newnum(t);
  121.   }
  122.   i = 0;
  123.   buf[i++] = c;
  124.   while (i<25) {
  125.     c=fgetc(f);
  126.     if (strchr(coper,c)) {
  127.       if (c=='(') {
  128.         p=newnode();
  129.         p->kind=FUN;
  130.         buf[i]=0;
  131.         strcpy(p->name,buf);
  132.         p->nump = 1;
  133.         return p;
  134.       }
  135.       ungetc(c,f); break;
  136.     }
  137.     if (c<=' ') break;
  138.     buf[i++] = c;
  139.   }
  140.   buf[i]=0;
  141.   if (!strcmp(buf,"e"))     return newnum(M_E);
  142.   if (!strcmp(buf,"pi"))    return newnum(M_PI);
  143.   return newvar(buf);
  144. }
  145. /*-----------------------------------------------------------------
  146.    load infix expression
  147. */
  148. node *loadinfix(char *filename) {
  149.   FILE *f;
  150.   node *tos,*p,*r,*t;
  151.   int i,y;              /* y == previous was a num or var */
  152.  
  153.   f = fopen(filename,"r");
  154.   if (f==NULL) {
  155.     printf(msg[3],filename);
  156.     pause;
  157.     return NULL;
  158.   }
  159.   tos = r = NULL;
  160.   *txt = y = 0;
  161.   p = gettoken(f,y);
  162.   while (p) {
  163.     if (*txt && p->kind<=NUM) {
  164.       p->msg = malloc(strlen(txt)+1);
  165.       strcpy(p->msg,txt);
  166.       *txt = 0;
  167.     }
  168.     if (y && (rpr[p->kind]==8 || rpr[p->kind]==1))  /* NEW EXPRESSION */
  169.       while (r) {                                   /* REDUCE ALL */
  170.         popr(t);
  171.         if (t->kind > EXP) continue;
  172.         t->nump = 2;
  173.         pop(t->rt);
  174.         pop(t->lf);
  175.         if (t->lf->msg) {
  176.           t->msg = t->lf->msg;
  177.           t->lf->msg = NULL;
  178.         }
  179.         push(t);
  180.       }
  181.     if (rpr[p->kind]==1) {         /* FUNC or StartPAREN */
  182.       pushr(p);
  183.       y=0;
  184.     }
  185.     else if (rpr[p->kind]==8) {           /* VAR and NUM */
  186.       push(p);
  187.       y=1;
  188.     }
  189.     else if (r && rpr[p->kind] <= rpr[r->kind] &&
  190.                                   p->kind != EXP) {   /* REDUCE */
  191.       popr(t);
  192.       if (t->kind > EXP) continue;
  193.       t->nump = 2;
  194.       pop(t->rt);
  195.       pop(t->lf);
  196.       if (t->lf->msg) {
  197.         t->msg = t->lf->msg;
  198.         t->lf->msg = NULL;
  199.       }
  200.       push(t);
  201.       continue;    /* don't get more input */
  202.     }
  203.     else if (r && r->kind==FUN && p->kind==CMA) {    /* COMMA */
  204.       r->nump++;
  205.       freenode(p);
  206.       y=0;
  207.     }
  208.     else if (r && r->kind==FUN && p->kind==EPA) {   /* END OF FUNCTION */
  209.       popr(t);
  210.       if (t->nump>MAXP) t->nump = MAXP;
  211.       for (i=t->nump; i--; ) pop(t->parm[i]);
  212.       if (t->lf->msg) {
  213.         t->msg = t->lf->msg;
  214.         t->lf->msg = NULL;
  215.       }
  216.       push(t);
  217.       freenode(p);   /* free close paren */
  218.       y=1;
  219.     }
  220.     else if (r && r->kind==SPA && p->kind==EPA) {   /* MATCH PARENS */
  221.       popr(t);
  222.       freenode(t);
  223.       freenode(p);
  224.       y=1;
  225.     }
  226.     else {
  227.       if (p->kind > EXP) {
  228.         printf(msg[4]);
  229.         pause;
  230.       }
  231.       else pushr(p);                        /* SHIFT */
  232.       y=0;
  233.     }
  234.     p = gettoken(f,y);
  235.   }
  236.   while (r) {                       /* REDUCE all remaining oper */
  237.     popr(t);
  238.     if (t->kind > EXP) continue;
  239.     t->nump = 2;
  240.     pop(t->rt);
  241.     pop(t->lf);
  242.     if (t->lf->msg) {
  243.       t->msg = t->lf->msg;
  244.       t->lf->msg = NULL;
  245.     }
  246.     push(t);
  247.   }
  248.   fclose(f);
  249.   return tos;
  250. }
  251.  
  252. /*--------------------------------------------------------------------
  253.    load a sample expression
  254. */
  255. node *load(char *filename) {
  256.   FILE *f;
  257.   static char tok[80];
  258.   node *tos,*p;
  259.   int i;
  260.   double t;
  261.  
  262.   f = fopen(filename,"r");
  263.   if (f==NULL) {
  264.     printf(msg[5],filename);
  265.     pause;
  266.     return NULL;
  267.   }
  268.   tos = NULL;
  269.   *txt = 0;
  270.   while (1) {
  271.     if (1 != fscanf(f,"%24s",tok)) break;
  272.     if (tok[0]==';') {
  273.       fgets(tok,sizeof tok,f);
  274.       continue;
  275.     }
  276.     if (tok[0]=='"') {
  277.       strcat(txt,tok+1);   i=strlen(txt);
  278.       fgets(txt+i,sizeof txt-i-2,f);
  279.       strcat(txt,"\r");
  280.       continue;
  281.     }
  282.     if (*tok=='?') {            /* --- Options ---- */
  283.       parse_option(f,tok+1);
  284.       continue;
  285.     }
  286.     if (*tok=='*') {        /* ------------------ */
  287.       p = newoper(MUL);
  288.       pop(p->rt);
  289.       pop(p->lf);
  290.       push(p);
  291.     }
  292.     else if (*tok=='=') {        /* ------------------ */
  293.       p = newoper(EQU);
  294.       pop(p->rt);
  295.       pop(p->lf);
  296.       push(p);
  297.     }
  298.     else if (*tok=='+